/**
  ******************************************************************************
  * @file    debug_print.c
  * @author  xing.dai@aliyun.com
  * @version V1.0
  * @date    2016 - 04 - 12
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptiBit_RESETs handler and
  *          peripherals interrupt service routine.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2015 STMicroelectrBit_RESETics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed Bit_RESET an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CBit_RESETDITIBit_RESETS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissiBit_RESETs and
  * limitatiBit_RESETs under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "debug_print.h"
/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define DEBUG_BUFFER_LENGTH 1024

#define DEBUG_MASK0		(1 << CRITICAL_LEVEL)
#define DEBUG_MASK1		(1 << ERROR_LEVEL)
#define DEBUG_MASK2		(1 << NORMAL_LEVEL)
#define DEBUG_MASK3		(1 << INFO_LEVEL)
#define DEBUG_MASK4		(1 << DEBUG_LEVEL)

#define PRIORITY0		DEBUG_MASK0
#define PRIORITY1		PRIORITY0 | DEBUG_MASK1
#define PRIORITY2		PRIORITY1 | DEBUG_MASK2
#define PRIORITY3		PRIORITY2 | DEBUG_MASK3
#define PRIORITY4		PRIORITY3 | DEBUG_MASK4

/* Private macro -------------------------------------------------------------*/

/* Public variables ----------------------------------------------------------*/
uint8 g_dbg_mask = PRIORITY4;

/* Private variables ---------------------------------------------------------*/
char g_printf_buf[DEBUG_BUFFER_LENGTH] = {0};

char const *const level_name[] = {
    "C",    // Critical
    "E",    // Error
    "N",    // Normal
    "I",    // Info
    "D",    // Debug
};

#if 0
#define PRINT_RED(s)    printf("\033[0;31m%s\033[0;39m",s);
#define PRINT_GREEN(s)    printf("\033[0;32m%s\033[0;39m",s);
#define PRINT_YELLOW(s)    printf("\033[0;33m%s\033[0;39m",s);
#define PRINT_BULE(s)    printf("\033[0;34m%s\033[0;39m",s);
#define PRINT_PURPLE(s)    printf("\033[0;35m%s\033[0;39m",s);/*??*/
#endif
/* Private function prototypes -----------------------------------------------*/
/* Private function ---------------------------------------------------------*/
static uint32 dbg_get_tick()
{
    OS_ERR err;

    return OSTimeGet(&err);
}

/**
  * @brief  Print debug infomation.
  * @param  level: debug priority.
  *         x_format: variable parameter.
  * @retval char number of print.
  */
unsigned int dbg_printf(uint32 level, int stamp, const char *x_format, ...)
{
    va_list args;
    uint32 cnt = 0;
    unsigned int tick = 0;
    char color[20] = "";
    device_t *console = console_get_device();

    if (g_dbg_mask & (1 << level)) {
        tick = dbg_get_tick();

        if (level >= sizeof(level_name) / sizeof(level_name[0])) {
            level = 2;
        }

        switch (level) {
            case 0: // Critical error.
                sprintf(color, "\033[0;31m");   // Red.
                break;
            case 1: // Error
                sprintf(color, "\033[0;35m");   // Purple
                break;
            case 3: // Info
                sprintf(color, "\033[0;32m");   // Green
                break;
            case 4: // Debug
                sprintf(color, "\033[0;33m");   // Yellow.
                break;

            default:    // Normal
                //sprintf(color, "\033[0;39m");   // white.
                break;
        }

        if (stamp == SHOW_STAMP)
            snprintf(g_printf_buf, DEBUG_BUFFER_LENGTH, "%s[%d.%03d]<%s>: ", color, tick / OS_CFG_TICK_RATE_HZ, tick % OS_CFG_TICK_RATE_HZ, level_name[level]);
        else
            snprintf(g_printf_buf, DEBUG_BUFFER_LENGTH, "%s", color);
        cnt = strlen(g_printf_buf);
        va_start(args, x_format);
        cnt = vsnprintf(g_printf_buf + cnt, DEBUG_BUFFER_LENGTH - cnt - 4, x_format, args);
        va_end(args);

        if (level != 2)
            strcat(g_printf_buf, "\033[0;39m");
        if (console == NULL) {
            printf("%s", g_printf_buf);
        } else {
            device_write(console, 0, g_printf_buf, strlen(g_printf_buf));
        }
    }
    return cnt;

}

/************************ (C) COPYRIGHT STMicroelectrBit_RESETics *****END OF FILE****/
